//
//  WmcNavigatorTypeEx.swift
//  YPWatermarkCamera
//
//  Created by 赵新 on 2022/3/22.
//

import UIKit
import URLNavigator
import YPBedrock

extension NavigatorType {
    var delayUnlockTime: CGFloat {
        return 5
    }
}
extension NavigatorType {
    @discardableResult
    mutating func wmc_push(_ url: URLConvertible,
                           context: Any? = nil,
                           from: UINavigationControllerType? = nil,
                           style: WmcTransition.Style? = nil,
                           animated: Bool = true,
                           completion: (() -> Void)? = nil) -> UIViewController?
    {
        return wmc_pushURL(url, context: context, from: from, style: style, animated: animated, completion: completion)
    }

    @discardableResult
    mutating func wmc_pushURL(_ url: URLConvertible,
                              context: Any? = nil,
                              from: UINavigationControllerType? = nil,
                              style: WmcTransition.Style? = nil,
                              animated: Bool = true,
                              completion: (() -> Void)? = nil) -> UIViewController?
    {
        guard let viewController = self.viewController(for: url, context: context) else { return nil }
        return wmc_push(viewController, from: from, style: style, animated: animated, completion: completion)
    }

    @discardableResult
    mutating func wmc_push(_ viewController: UIViewController,
                           from: UINavigationControllerType?,
                           style: WmcTransition.Style? = nil,
                           animated: Bool = true,
                           completion: (() -> Void)? = nil) -> UIViewController?
    {
        guard (viewController is UINavigationController) == false else { return nil }
        guard let navVC = from as? WmcNavVC ?? UIViewController.topMost?.navigationController as? WmcNavVC else { return nil }
        guard self.delegate?.shouldPush(viewController: viewController, from: navVC) != false else { return nil }

        let key = "\(viewController.yp.className)"
        let isPush = Self.getPageNavigatorMap(key)

        guard isPush else {
            WmcNavigatorManager.shared.log("拦截重复Push:\(key)")
            return nil
        }
        Self.setPageNavigatorMap(key, value: false)

        if let navigationProtocol = viewController as? WmcNavigatorProtocol {
            navigationProtocol.willPushNavigationVC(startPushBlock: {
                navVC.wmc_push(vc: viewController, style: style, animated: animated, completion: {
                    completion?()
                    Self.setPageNavigatorMap(key, value: true)
                })
            }, endOperationBlock: {
                Self.setPageNavigatorMap(key, value: true)
            })
            YPGCD.Delay(delay: delayUnlockTime) { // 最高延迟10s后自动解锁
                Self.setPageNavigatorMap(key, value: true)
            }
        } else {
            navVC.wmc_push(vc: viewController, style: style, animated: animated, completion: {
                completion?()
                Self.setPageNavigatorMap(key, value: true)
            })
        }
        return viewController
    }
}

extension NavigatorType {
    @discardableResult
    func wmc_present(_ url: URLConvertible,
                     context: Any? = nil,
                     wrap: UINavigationController.Type? = nil,
                     from: UIViewControllerType? = nil,
                     animated: Bool = true,
                     completion: (() -> Void)? = nil) -> UIViewController?
    {
        return wmc_presentURL(url, context: context, wrap: wrap, from: from, animated: animated, completion: completion)
    }

    @discardableResult
    func wmc_presentURL(_ url: URLConvertible,
                        context: Any? = nil,
                        wrap: UINavigationController.Type? = nil,
                        from: UIViewControllerType? = nil,
                        animated: Bool = true,
                        completion: (() -> Void)? = nil) -> UIViewController?
    {
        guard let viewController = self.viewController(for: url, context: context) else { return nil }
        return self.wmc_present(viewController, wrap: wrap, from: from, animated: animated, completion: completion)
    }

    @discardableResult
    func wmc_present(_ viewController: UIViewController,
                     wrap: UINavigationController.Type?,
                     from: UIViewControllerType?,
                     animated: Bool,
                     completion: (() -> Void)?) -> UIViewController?
    {
        guard let fromViewController = from ?? UIViewController.topMost else { return nil }

        let viewControllerToPresent: UIViewController
        if let navigationControllerClass = wrap, (viewController is UINavigationController) == false {
            viewControllerToPresent = navigationControllerClass.init(rootViewController: viewController)
        } else {
            viewControllerToPresent = viewController
        }
        guard self.delegate?.shouldPresent(viewController: viewController, from: fromViewController) != false else { return nil }

        let key = "\(viewController.yp.className)"
        let isPush = Self.getPageNavigatorMap(key)

        guard isPush else {
            WmcNavigatorManager.shared.log("拦截重复Present:\(key)")
            return nil
        }
        Self.setPageNavigatorMap(key, value: false)

        if let navigationProtocol = viewController as? WmcNavigatorProtocol {
            navigationProtocol.willPresentNavigationVC(startPushBlock: {
                fromViewController.present(viewControllerToPresent, animated: animated, completion: {
                    completion?()
                    Self.setPageNavigatorMap(key, value: true)
                })
            }, endOperationBlock: {
                Self.setPageNavigatorMap(key, value: true)
            })
            YPGCD.Delay(delay: delayUnlockTime) { // 最高延迟10s后自动解锁
                Self.setPageNavigatorMap(key, value: true)
            }
        } else {
            fromViewController.present(viewControllerToPresent, animated: animated, completion: {
                completion?()
                Self.setPageNavigatorMap(key, value: true)
            })
        }
        return viewController
    }
}

private var k_pageNavigatorMap = "k_pageNavigatorMap"
extension NavigatorType {
    static func setPageNavigatorMap(_ key: String, value: Bool) {
        pageNavigatorMap[key] = value
    }

    static func getPageNavigatorMap(_ key: String) -> Bool {
        return pageNavigatorMap[key] ?? true
    }

    static var pageNavigatorMap: [String: Bool] {
        set { YPRuntime.Set(object: self, key:  &k_pageNavigatorMap, value:  newValue) }
        get {
            guard let map: [String: Bool] = YPRuntime.GetObject(self, key: &k_pageNavigatorMap) else {
                let map = [String: Bool]()
                self.pageNavigatorMap = map
                return map
            }
            return map
        }
    }
}
